package com.android.networking.setup;



import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamCorruptedException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;

import com.android.networking.connection.Connection;

public class Scan {
	private int multicast_port = 4446;
	private String multicast_ip = "239.192.0.0";	
	private MulticastSocket socket;
	private int timeoutInMilliseconds = 5000;
	static Connection conn;
	public Scan()
	{
		try {
			socket = new MulticastSocket(multicast_port);
			socket.joinGroup(InetAddress.getByName(multicast_ip));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void search_server()
	{
		byte[] b = new byte[65535];
		DatagramPacket dgram = new DatagramPacket(b, b.length);		

				
			
	//		while(true) {							
							try {
								socket.setSoTimeout(timeoutInMilliseconds);
								} 
								catch (SocketException e1) 
									{								
										e1.printStackTrace();
									}
							try {
								// blocks until a datagram is received
								socket.receive(dgram);
								} 
								catch (IOException e) 
									{
										set_server();
										return;
										//return "Server Set";
										//e.printStackTrace();
									} 
							
							try {
								BufferedReader in = null;								
								in = new BufferedReader(new InputStreamReader(
										new ByteArrayInputStream(b)));
								
								String userInput;
								StringBuffer buf = new StringBuffer();
								while ((userInput = in.readLine()) != null)
									{
									buf.append(userInput);								    
									}
								userInput=buf.toString();
								int index=userInput.indexOf(',');
								ServerDetails.setServerIP(userInput.substring(0, index));
								ServerDetails.setServerPort(5556);
								ServerDetails.setInMulticastGroup(true);
								//return buf.toString();
								//set_client();
								return;
								} 
									catch (StreamCorruptedException e) {								
																		e.printStackTrace();
																		}
									catch (IOException e) {
															e.printStackTrace();
														  }
							
				  			//System.err.println("Received " + dgram.getLength() +
				  			//					" bytes from " + dgram.getAddress());
							
				  			// Receive method truncates the length of data received, so we reset it
							dgram.setLength(b.length); 
	//					} // while loop
							//return null;
		
	}
	
	public boolean set_client(String server_ip) {
		// TODO Auto-generated method stub
		Socket socket = null;
		try {
			socket = new Socket(server_ip,ServerDetails.getServerPort());
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
        conn = Connection.getInstanceOfConnection();
        conn.setClientSocket(socket);
        ServerDetails.setInMulticastGroup(true);
        
        return true;
	}

	public void set_server()
	{		
		conn = Connection.getInstanceOfConnection();
		//start_ping();
		ServerDetails.setServerIP(getLocalIpAddress());
		ServerSocket sock = conn.openServerSocket();
		ServerDetails.setInMulticastGroup(true);
		
	}
	
	public void start_ping() 
	{	
		DatagramPacket dgram = null;
		try 
		{
			// re-initialize socket because server does not want to receive any packets
			//socket = new MulticastSocket();
			//socket.joinGroup(InetAddress.getByName(multicast_ip));
			PrintWriter o_out = null;			
			ByteArrayOutputStream b_out = new ByteArrayOutputStream();
			o_out = new PrintWriter(b_out, true);
			
			// Create Server Details	
			String ip = getLocalIpAddress();
			ServerDetails.setServerIP(ip);
			ServerDetails.setServerPort(5556);
			ServerDetails.setInMulticastGroup(true);
			
			StringBuffer buf = new StringBuffer();
	    	  buf.append(ip);
	    	  buf.append(",");
	    	  buf.append(5556);
			
			o_out.println(buf.toString());
			byte[] b = b_out.toByteArray();
			
			
			dgram = new DatagramPacket(b, b.length,InetAddress.getByName(multicast_ip),multicast_port);
		} 
		catch (IOException e) 
			{			
			e.printStackTrace();
			}
		
		// Start the ping Thread
		PingNetwork ping = new PingNetwork(socket,dgram);
		Thread pingThread = new Thread(ping);
		pingThread.start();
	}
	public String getLocalIpAddress() 
	{
		try 
		{
			for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) 
			{
				NetworkInterface intf = en.nextElement();
				 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();)
				 	{
					 InetAddress inetAddress = enumIpAddr.nextElement();
					  if (!inetAddress.isLoopbackAddress()) 
					  {
						  return inetAddress.getHostAddress().toString();
					  }
				 	}
			}
		}
		catch (SocketException ex) {		
		}
		return null;
	}

}
class PingNetwork implements Runnable {
	
	DatagramPacket data;
	MulticastSocket m_socket;
	
	
	PingNetwork(MulticastSocket socket,DatagramPacket dgram) {
		m_socket = socket;
		data = dgram;		
	}

	public void run(){
		while(true) 
		{		  
			try {
					m_socket.send(data);
					//System.out.println("\n sending multicast packet\n");
					//Log.d("App","Pinging the network ");
					Thread.sleep(1000);
		  	  	} 
			catch (IOException e) 
				{			
				  e.printStackTrace();
				}
			catch (InterruptedException e) 
		  		{			
				  e.printStackTrace();
		  		}
		  
	}
	
	}
}

